Developer --> Technical Publications
PATH  Mac OS X Server Documentation > Mac OS X Server Release Notes


[Back]

MacOS X Server Release Notes Copyright \xa9 1998 by Apple Computer, Inc. All Rights Reserved.

Mac OS X Server Developer Release Notes:
Foundation Framework

The Foundation Framework is a library of Objective-C classes that provide the infrastructure for object-based applications without graphical user interfaces as well as for most other Yellow Box frameworks, most notably the Application Kit. Foundation consists of basic classes used by any Objective-C program:

The Foundation Topics section covers the following subjects:

The release note Implications of the Year 2000 for Rhapsody also contains Foundation-related information of interest to developers.


Notes Specific to Developer Release 2

Changes from Developer Release 1

There have been many bugs fixed and improvements made in Foundation since Developer Release 1 (DR1). An overview of the changes to public API follows.

Added Headers

Added Classes

Added Methods

Added Functions

Deleted Headers

Deleted Classes

Deleted Methods

Deleted Functions

 

File Access APIs

The Rhapsody DR1 release notes mentioned that the NSFileManager class would be obsolesced in favor of a new File Access API in the Customer Release. We will not obolesce NSFIleManager any time soon, so continue using NSFileManager as the means to manipulate files through the Yellow Box.

In this release, there is a new NSURL class that provides a way to refer to files via URLs; however, it does not provide the rich set of file-manipulation methods provided by NSFileManager.

 

New Directory Structure Layout

In this release a new directory structure for system, local, and network files has been introduced. See the document Rhapsody File System Conventions, which describes the names, locations, and typical contents of the standard directories for these types of files. It also discusses the search paths used for locating files.

 

NSPPL Obsolesced

All of the functionality provided by NSPPL.h in Foundation is deprecated and has been removed from the Foundation binary in this release. No binary compatibility efforts are made for DR1 applications which used the symbols in NSPPL.h. The NSPPL.h header has also been removed.

To support developers who may have been using NSPPL, this class and its support classes will be packaged into a PPL framework and released in source form in one of these two ways:

 

Locale-Sensitive Compare

In Developer Release 2 the compare methods of NSString have been augmented to provide the capability for linguistically correct locale-sensitive comparison. The new comparison routine is accessible through a new locale argument to compare:. It is also accesible with two new methods, localizedCompare: and localizedCaseInsensitiveCompare:, which assume a default locale. The binary comparison is still available using the non-primitive forms of compare:, the primitive form of compare: with nil as the locale argument or caseInsensitiveCompare:.

The routine currently uses a single ordering which is correct for English, French, German, Japanese, and several additional Western European languages (but not Spanish or Scandinavian languages). Thus, the value of the locale argument (or the identity of the default locale) is currently ignored. The strings are compared using the data in the Collation Element Table from the Unicode Consortium (http://www.unicode.org) and the result should be consistent with the linguistic requirements of The Unicode Standard, Version 2.0, Section 5.15 "Sorting and Searching,"with the following limitations:

Note that the Unicode Standard ordering (as well as the ISO14651 ordering) treats most punctuation and whitespace characters as ignorable.


Notes Specific to Developer Release 1

TimeZoneInfo/README.TimeZoneInfo

Most of the information in the file TimeZoneInfo/README.TimeZoneInfo in the Resources directory of the Foundation framework is obsolete, but did not get updated for the release.

For information on updating the time zone data built into Foundation, refer to the section Foundation's Time Zone Data below. The built-in time zone data for Developer Release is from July, 1997. For the Rhapsody Premier release it will be updated to at least be that current on 1 February 1998.

 

NSPPL is Obsolesced

The functionality provided by NSPPL.h in Foundation is deprecated in this release and will be removed from the Foundation binary in Customer Release 1. No binary compatibility efforts will be made for current applications that use the symbols in NSPPL.h.

In this release, the import of NSPPL.h has been removed from the convenience header Foundation.h, and a #warning has been placed in NSPPL.h itself warning of the obsolescence.

To support developers who might have been using NSPPL, one or more of the following actions will be taken by Apple:


Foundation Topics

 

Foundation's Time Zone Data

The Foundation now uses its own time-zone data files on all platforms. These files describe when changes to the standard time zone corrections from GMT occur. This data promotes greater consistency of behavior, and makes it possible to unarchive and transport time zones to any platform on which Foundation is installed. However, time-zone data can become out of date relative to a particular platform's data as, for example, when new operating system updates are installed, but the new versions of Foundation are not.

The Foundation's time-zone data comes from a freely available source at elsie.nci.nih.gov. The reason for choosing the data from elsie.nci.nih.gov is that it is an easily accessible, and quite complete, source of current information. The Foundation also adopts the zone naming conventions of that data, where zone names usually have the form Area/Location, as in America/Sao_Paulo or Europe/Paris. The locations are usually large population centers.

How time-zone abbreviations map to time zone names is an arbitrary choice of the Foundation, since time-zone abbreviations are ambiguous. Use of time-zone abbreviations is not encouraged.

The built-in time zone data for the Developer Release 2 is from July, 1997. For Customer Release 1, it will be updated to at least be that current on 1 May 1998.

 

Updating the Data for a Time Zone

To update a time zone's data, one simply has to drop a data file in the correct format (naming that time zone) into the Foundation framework's Resources/TimeZoneInfo directory. For example, suppose that the Italian government decided to change when Italy goes off daylight-saving time. The time zone covering most of Italy is "Europe/Rome". Given the corrected data file, a directory named"Europe" (if it doesn't exist) needs to be created inside the TimeZoneInfo directory, and the data file placed in TimeZoneInfo/Europe, and named "Rome". If the system time zone is set to Europe/Rome, Foundation will use the new data file rather than its built-in data for Europe/Rome whenever necessary.

Where does the corrected data file come from? Apple may release corrected data files from time to time. You can access the source of Foundation's time-zone data from ftp://elsie.nci.nih.gov/pub/ in a file called tzdata*.tar.gz (the part of the name indicated by the "*" changes from time to time), and the "compiler" for this data is in an archive called tzcode*.tar.gz in the same location. The compiler needs to be built, and then used to compile the raw description files into time zone data files. Generally this can only be done by a developer. The process goes something like this:

 

 

Using performSelector: with Selectors That Don't Return id

The NSObject instance methods performSelector:, performSelector:withObject:, and performSelector:withObject:withObject:have a return value of id. This is a vestige of pre-OpenStep conventions where methods without otherwise interesting return values returned self. Much of the time one can "get away with" performing a selector on an object with these methods, where the target method does not have a return value or has a non-object return value. Such use is semantically suspect, however, and is not valid.

Any situation where the performSelector: message (and variants) is forwarded illustrates this (with an abnormal program termination); the NSInvocation object attempts to retain the return value from after invocation because the selector for performSelector: is typed to return an object. Sending performSelector: to a faulted object with a selector that does not return id is an example of this. This behavior extends also to various other "perform" methods such as the makeObjectsPerformSelector: of some collection classes and the "delayed perform" and "ordered perform" methods in NSRunLoop.h.

 

 

Where Do Logged Messages Go?

The NSLog() and NSLogv() functions do not log an error message to stderr, as stated in the documentation.

On HP-UX, Solaris, and Mach systems (such as Rhapsody), these functions write the log to STDERR_FILENO if the file descriptor is open. If that fails, the function sends the message to the syslog subsystem with the LOG_USER facility (or default facility if LOG_USER doesn't exist on a platform) and with priority LOG_ERR (or similar, depending on what the platform supports). If both of these attempts to write the message fail, the message is discarded.

On Windows platforms, the message is written to the STD_ERROR_HANDLE, if that standard handle is valid and supported on the system. It is also written to the Windows Event Log on Windows platforms that support the Event Log; otherwise it is written to the file c:\fndation.log (if that file can be opened). If all of these attempts fail, the message is discarded. On some Windows platforms, the message to the Event Log may be truncated if there is a limit to the size of a message that the Event Log can accept. Note that this implies that the Event Log can fill up with NSLog()-generated messages, thus causing application crashes. You should be aware of this and make the appropriate settings in the Event Log application to discard old messages.

On Windows platforms that support an application discovering whether or not it is running under a debugger, NSLog() and NSLogv() may only send the message to the debugger for its handling, via standard WIN32 mechanisms, and not also write the message to STD_ERROR_HANDLE and the Event Log. Note that a debugger may choose not to display messages thus sent to it, or may choose not to display all messages; NSLog() and NSLogv() have no control over that.

Output from NSLog() and NSLogv() is serialized, in that only one thread in a process can be doing the logging described above at a time. All attempts at logging a message complete before the next thread can begin its attempts.

The effects of NSLog() and NSLogv() are not serialized with subsystems other than those discussed above (such as the standard I/O package) and do not produce side effects on those subsystems (such as causing buffered output to be flushed, which may be undesirable).

The format specification allowed by NSLog() and NSLogv() is that which is understood by NSString's formatting capabilities. That is not necessarily the set of format escapes and flags understood by the printf() function, as mentioned in the documentation.

 

Archiving

NSUnarchivers own the objects that they decode. When an NSUnarchiver is deallocated, so are the objects that it has decoded, unless they have been retained. The following code, for example, will probably result in a decoded object being used after being freed:

    NSAutoreleasePool *pool = [[NSAutoreleasePool allocWithZone:NULL] init];
    NSUnarchiver *unarchiver = [[NSUnarchiver allocWithZone:NULL] initForReadingWithData:myData ];
    id object = [unarchiver decodeObject];
    [unarchiver release];
    [pool release];
    .. use or return  object here ...

The object object should be retained before the NSUnarchiver is released, and probably should also be autoreleased if object is returned from the function or method. Exceptions to this are the instance methods decodeValueOfObjCType:at: and decodeValueOfObjCTypes: (and variants). Objects "returned" from these two methods, like those returned from NSObject's allocWithZone: and copyWithZone:, are not autoreleased and must be explicitly released.

 

Errors in ASCII Property Lists

When a method like NSDictionary's dictionaryWithContentsOfFile: is used to read and parse an ASCII property list from a file, the display of parse errors and exceptions is suppressed, and nil is returned upon error. However, you might want to know about syntax errors in a property list, or you might want finer-grained information about why a property list cannot be read and parsed. You can use another method, NSString's propertyList, for this purpose. The following example illustrates this technique:

- (id)readPropertyListFromFile:(NSString *)path mustBeOfType:(Class)targetClass 
logErrors:(BOOL)showErrors {
    NSString *string;
    id plist = nil;
     string = [[NSString allocWithZone:NULL] initWithContentsOfFile:path];
    if (showErrors && nil == string) {
        NSLog(@"%@: string could not be read from '%@'", NSStringFromSelector(_cmd), path);
    }
    NS_DURING
        plist = [string propertyList];
    NS_HANDLER
        if (showErrors) {
            NSLog(@"%@: received exception while parsing: %@", NSStringFromSelector(_cmd), 
                localException);
        }
        plist = nil;
    NS_ENDHANDLER
    [string release];
    if (nil != targetClass && ![plist isKindOfClass:targetClass]) {
        if (showErrors) {
            NSLog(@"%@: property list is not of desired type '%@'. It's an '%@'.",
                NSStringFromSelector(_cmd), NSStringFromClass(targetClass), 
                NSStringFromClass([plist class]));
        }
        [plist release];
        plist = nil;
    }
    return plist;
}
 

 

Grammars for Serialization and ASCII Property List Formats

Grammars and description of the serialization (NSSerializer) and ASCII property list representation formats are available in the appendix to the OpenStep specification. Strings containing non-alphanumeric characters must be double-quoted in property lists to ensure the parsing of the entire string as one string object; otherwise, parse failures will result.

 

Retain Cycles and Invalidation

The retain/release strategy used in Foundation allows an incautious programmer to create reference cycles in an object graph (that is, the graph of objects that retain one another in some manner). These cycles are self-sustaining and constitute a memory leak. The simplest example is the creation of an NSMutableArray instance that is then added to itself. Since an array retains its objects, it retains itself independent of its normal usage. The effects of retaining are essentially distributed across the network via the Distributed Objects mechanism.

If you cannot avoid retain cycles by careful design, but know about their existence, you can use the following technique to recover the memory. For the objects in a retain cycle whose retain counts are solely due to the cycle, you should retain all objects (perhaps in an array), then tell each one to release its retained objects, then release all objects. The action of releasing its retained objects would undoubtedly cause an object to become dysfunctional. Some objects already implement such a method by the name "invalidate". It is a bug that neither NSObject nor the collections implement this method to facilitate cycle recovery.

 

More on Autoreleasing and Retaining

The following statements are false:

Returned objects are guaranteed to be valid for the scope of the current method.
Returned objects are guaranteed to be valid until the current autorelease pool is released.
Returned objects are guaranteed to be valid until the end of the current event loop.

The Foundation's retain count mechanism operates through the NSObject methods retain and release. A code fragment such as:

    id object = [collection returnObject];

creates a reference (in object) to the returned object, but does not increment the retain count of object. If you don't let the system know about your reference, by incrementing the retain count with retain, the system can't ensure that your reference remains valid for any length of time. For example:

    object = [array objectAtIndex:7]; /* get object */
    [array removeObjectAtIndex:7]; /* removes object and releases it */
    [object dosomething ]; /* object may be invalid here */

In this example, if array had the last retain on object, the second line will cause object to be deallocated and the third line will cause the application to crash. Here is another example with the Application Kit:

    id oldTitle = [myWindow title]; /* get current title */
    [myWindow setTitle:@"Calculating..."]; /* set temporary title */
    /*... do calculation here ... */
    [myWindow setTitle:oldTitle]; /* restore previous title */

Here, the setTitle: method gets rid of its reference to the existing title string and takes a reference to the new title string. If the window had the only reference to the previous title string object, the last line of the example will attempt to use setTitle: with a freed object. If the Application Kit in its implementation happens to send autorelease to the old title instead of release, then the object referenced in oldTitle might not be freed by the last line, but in general you cannot know whether such a method will release or autorelease the previous object. The Foundation almost exclusively uses release, since that does not have the performance overhead of autoreleasing, and Foundation objects are very common in applications.

In practice, you can get away with such "weak references" much of the time. But the safest approach formalizes your reference to the object:

    id object = [[collection returnObject] retain];
    /*... do operations, some of which may be on "object" ... */
    /* Don't need object any longer */
    [object release];
    object = nil;

 

Thread-safe Classes in Foundation

It is commonly believed that "the Foundation is thread-safe and the Application Kit is not". However, this statement is a gross generalization and can be misleading. There are varying degrees of thread-safety, and each person has their own definition of "thread-safety". The issue of "re-entrancy" is also often confused with thread-safety. For the purposes of this note, these terms are defined as follows:

Thread-safe
Able to have operations invoked simultaneously by multiple threads of execution on an instance without that producing invalid results or an inconsistent or corrupt state within the instance.
Re-entrant
Able to be invoked recursively, while one or more operations on the same instance are pending completion in higher (less recent) frames of a thread's call stack.

Changes to the Objective-C or Java runtimes by threads while other threads are present are outside the scope of this note.

Some objects are thread-safe because they are immutable and thus can't be modified. This doesn't prevent one thread from deallocating the object "out from under" another thread's use.

Also note that where there are immutable and mutable types of the same general type of object (like NSString/NSMutableString), that since the immutable type (like NSString) is used both as the general type and the immutable type that you cannot depend on the immutability of the type providing thread-safety. For example, if the return value of a method is "NSString *", you cannot depend on that object being unchangable and thread-safe, since an instance of NSMutableString (or some other subclass of NSString) could actually be returned. In fact this applies in general: since an instance of any subclass of X could be returned (or passed as a parameter) for a type "X *", and such subclasses may or may not be thread-safe (and/or re-entrant), you cannot depend on the thread-safety of the type "X *" extending to whatever object you may receive satisfying type "X *".

Finally note that re-entrancy is only possible where operations "call out" to other operations in the same object or on different objects. Retaining and releasing objects is one such "call out" which is sometimes overlooked.

These facilities are generally thread-safe:

The following facilities are generally not thread-safe:

* Note that while these classes might be thread-safe or not, it is not safe to change the underlying data or structure of the underlying data while these objects are in use. For example, in the case of an archiver, it is not safe to change the object graph being archived. For an enumerator, it is not safe for any thread to change the enumerated collection.

Some of the non-thread-safe facilities may be made thread-safe in the future.

The following classes are explicitly re-entrant. All other classes may or may not be re-entrant. Note that a complete analysis for re-entrancy has never been done and this list may not be exhaustive.

Some of the non-re-entrant facilities may be made re-entrant in the future.

 

The -hash and -isEqual: Invariant

An obscure requirement documented in the NSObject class specification for the hash method deserves elaboration. The hash and isEqual: methods of a class must be defined so that if two objects are equal, their hash value is the same. Thus

    [x isEqual:y] 

implies

    [x hash] == [y hash]

However, the converse is not true. This is easy to forget, but especially important to keep in mind when putting custom objects into some collections (such as NSSet and NSDictionary objects).

 

Forwarding Messages

Objects wishing to forward messages with the forwardInvocation: method must also override the methodSignatureForSelector: method. This requirement results from the compiler not providing call-stack descriptive information at each call site. Consequently, the run time needs a source of information for how the stack frame is constructed. It needs this information to build the invocation that will be supplied to the forwardInvocation: method call. The methodSignatureForSelector: method must be reimplemented to provide a method signature for selectors to which the object does not respond.

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
    NSMethodSignature *result = [super methodSignatureForSelector:sel];
     // if result is nil, self must not respond to the selector
    if (nil == result)
        result = [target methodSignatureForSelector:sel];
    return result;
}
 - (void)forwardInvocation:(NSInvocation *)invocation {
    [invocation invokeWithTarget:target]; // let target implement methods that we do not
}

Faulted objects in EOF that wish to forward messages should also override the class method instanceMethodSignatureForSelector:. See the ForwardInvocation example in /NextDeveloper/Examples/Foundation/ForwardInvocation.

 

Debugging Aids

The header file NSDebug.h has some global flags, functions, and methods that you may find useful in debugging. But be advised: Although this header file is public, its contents are mostly unsupported, largely undocumented, and subject to change without warning. Do not depend on APIs within this header for the operation of production programs.

 

Object Allocation Analysis

One of the useful flags defined in NSDebug.h is NSKeepAllocationStatistics, which allows you to analyze the object allocation activity in a program. You can use the ObjectAlloc demo application that comes with Rhapsody and Yellow Box for Windows to graph the object allocation activity in real time.

 

The load Method

The load message is sent to classes when they are added to the Objective-C run time. Defined as a class method in NSObject, load is usually sent before initialize. Subclasses of NSObject do not inherit load.The order in which load messages are sent to classes is unspecified (and specifically, a class's superclass is not guaranteed to have its load method called before the class receives the message). Therefore, you should not use any subsystems or classes that are loaded at the same time if you do not know they have received the load message. If you do, you will probably cause execution of code that assumes that load (and anything that had to be done in load) has been previously invoked.

Typically, classes get added to the run time in one of two ways: when loaded dynamically from a bundle or framework, or by NSBundle at application launch. The restrictions on load are perhaps most serious at launch time. The Foundation has classes and subsystems (as might any other library) that depend on load being invoked before they are fully functional. For example, you should not use NSZoneMalloc() to allocate memory in load methods in objects that are statically linked into an application. You certainly should not create any objects or do anything that creates objects.

Note that sending load to a class isn't a solution (and is a generally bad idea), because that will cause initialize to be sent first, which the class may not handle. Moreover, sending load places into your code dependencies on which classes implement load in a particular version of a library. In the case of Foundation, for convenience sake, load methods that must use Foundation API can call send self to NSObject first to make sure Foundation has performed the initialization it needs.

The load method is not intended as a general initialization mechanism and should be used only when absolutely necessary. Use initialize for early initialization whenever possible.

 

Performance and NSNotificationCenter

NSNotificationCenter, although heavily optimized, can become a performance bottleneck if application code makes heavy use of notifications. Use the notification mechanism judiciously.

 

NSAutoreleasePool's addObject: Instance Method

You should never use the NSAutoreleasePool instance method addObject: to autorelease an object. Instead use the autorelease method or the class method addObject:. Using the instance method incurs the risk of adding an object to a pool that is not the top autorelease pool, a semantically suspect operation, since the autorelease-pool model is one of a (per-thread) stack of pools. Rhapsody does allow you to add objects to an autorelease pool that is not the top pool, but it is a much more expensive operation than adding an object to the top pool.

 

Frameworks as NSBundles

Frameworks are a specialized form of bundle. An application can statically link against a framework at compile time (like a library), or dynamically load a framework (like a bundle) at run time. However, as a specialized type of bundle, there are some constraints placed on frameworks:



 

Known Problems and Fixed Bugs

This section documents many of the known problems with Foundation in Rhapsody Developer. Not all of the problems apply to the current release; refer to the Releases and Disposition fields for each problem. Defects not present in the current release are of interest to those developing software on the current release with plans to deploy on a previous release. (However, we do not recommend that developers develop on a version newer than that planned for deployment.)


Reference

47347

Releases

Rhapsody Developer

Platforms

All

Disposition

None

Problem

NSArchiver and NSUnarchiver do not understand bitfields.

Description

Structures containing bitfields cannot be archived and unarchived.

Workaround

Encode the members of a structure containing bitfields individually, encoding the bitfields as char, short, or int (or unsigned char, short, or int as appropriate).


Reference

49084

Releases

Rhapsody Developer

Platforms

All

Disposition

None

Problem

NSInvocation always retains the return value.

Description

NSInvocation always retains object return values. This can cause problems if the return value of a method is not a fully initialized object. Only the NSObject class methods alloc and allocWithZone: return uninitialized objects, so this is only a problem if a program uses invocations to send either of those messages to a class object. If an application has its own methods that return objects which are not fully initialized, it should avoid sending those messages with an NSInvocation or over Distributed Objects.

Workaround

None


Reference

51108

Releases

Rhapsody Developer

Platforms

All

Disposition

None

Problem

Kanji text in NSLog() functions shows as Unicode hex on Japanese systems.

Description

Strings that contain non-ASCII characters are displayed with the non-ASCII characters translated to a hex representation (\uNNNN). This makes log strings with Kanji essentially unreadable.

Workaround

None


Reference

56644

Releases

Rhapsody Developer

Platforms

All

Disposition

None

Problem

NSArchiver tracks char * pointers as equivalent to their contents.

Description

During archiving, NSArchiver keeps track of the char * strings it has seen by the address passed in for encoding. If a program uses the stack or malloc() to construct a char *, then encodes it using the "*" type primitive (or @encode(char *)), the archiver only remembers the stack or malloc() address, assuming it has constant contents.

Workaround

Do not archive char * strings from the stack. Do not mutate or free malloc'd char * strings during archiving.


Reference

56659

Releases

Rhapsody Developer

Platforms

All

Disposition

None

Problem

Proxies cannot be notification observers unless they are retained.

Description

Because NSNotificationCenter does not retain observers, registering an observer with a remote NSNotificationCenter (the observer would be a proxy in the remote process) will eventually cause a crash of the remote process when it tries to send a message to a freed object, unless the remote process explicitly retains the proxy. This situation is a bit arcane, but the same type of problem can happen with other objects that don't retain objects that they know about.

Workaround

Use an explicit protocol to tell the server (the process vending the notification center) to register and unregister an observer. The server then retains and registers the observer with the vended notification center, and unregisters and releases the observer when the client tells it to do so. (If an unregister mechanism is not part of the protocol, and used, the object will never be released.)


Reference

57984

Releases

Rhapsody Developer

Platforms

All

Disposition

None

Problem

Can't get a list of command-line arguments that are not defaults.

Description

There is no way to get a list of the process arguments that NSUserDefaults did not interpret as default vaules.

Workaround

The NSArgumentDomain dictionary can be retrieved from the standard user defaults instance to find out what arguments were interpreted as default options.


Reference

58137

Releases

Rhapsody Developer

Platforms

All

Disposition

None

Problem

Can't create an NSData object that does not free the bytes.

Description

NSData and NSMutableData instances always take ownership of the byte pointer with which they are initialized, and then call free() to free the storage when they are deallocated. This fact applies to all existing creation and initialization methods. Only pointers to storage that can be passed to free() should be used to initialize data objects. As a corollary problem, there is no way to create a data object that refers to VM-allocated storage.

Workaround

None.


Reference

62235

Releases

Rhapsody Developer

Platforms

All

Disposition

None

Problem

Can't search for characters in a case-insensitive mode.

Description

NSString's rangeOfCharactersFromSet: ignores the NSCaseInsensitiveSearch flag. This problem also affects NSScanner's scanCharactersFromSet:intoString: method when the scanner has been set to be case insensitive.

Workaround

None.


Reference

62576

Releases

Rhapsody Developer

Platforms

All

Disposition

None

Problem

NSNumber's compare: method yields odd results with NaN.

Description

Two NSNumbers containing NaN are compared and seem to be equal; for example, they are created with numberWithDouble: and compare NSOrderedSame when isEqual: is invoked on them. However, in C, NaN is not equal to NaN.

Workaround

None.


Reference

62812

Releases

Rhapsody Developer

Platforms

All

Disposition

None

Problem

Changes to defaults sometimes appear not to take effect.

Description

The default search order for domains in NSUserDefaults places the NSArgumentDomain before the application's domain. This is usually desirable for reading defaults, but may not be what you want if you set or otherwise change default values. If you set a value for a default that was passed as an option on the command-line, the value is correctly set in the application's domain, but objectForKey: will still return the value found in the NSArgumentDomain, because by default that domain is searched first.

Workaround

The available workarounds depend upon the application and its use of user defaults. The following options pertain to a specific NSUserDefaults instance; if you create multiple instances of NSUserDefaults, you'd have to do the workaround for each individually.

  • Remove the NSArgumentDomain from the search list, perhaps after adding any keys it contains to the registration domain. However, a consequence of this approach is that defaults specified on the command line will not be found, nor will they have priority over same-keyed defaults in the application's domain.

  • Move the NSArgumentDomain after the application's domain; a consequence of this approach is that defaults specified on the command line will not have priority over same-keyed defaults in the application's domain.

  • Each time you set a default value, set it in the argument domain (this approach is difficult and not worth the trouble).

  • The best solution is this: Create a subclass of NSUserDefaults. For each defaults instance created, create a new volatile domain, tell the instance about it (setVolatileDomain:forName:), perhaps calling it "ChangedDefaults" (don't give it a name beginning with "NS"!). Then insert the new domain first in the domain search list of the new defaults instance. Override the setObject:forKey: and removeObjectForKey: methods to set and remove the value in the "ChangedDefaults" volatile domain. Then call super's methods of the same names to do the same for the application domain. The following code illustrates what these override methods might look like.
    - (void)setObject:(id)value forKey:(NSString *)defaultName {
        NSDictionary *changedDomain;
        id oldValue;
         [super setObject:value forKey:defaultName];
        changedDomain = [self volatileDomainForName:@"ChangedDefaults"];
        oldValue = [changedDomain objectForKey:defaultName];
        if (![oldValue isEqual:value]) { // Something to do
            NSMutableDictionary *newDomain;
            newDomain = [[NSMutableDictionary allocWithZone:[self zone]]
                initWithDictionary:changedDomain];
            [newDomain setObject:value forKey:defaultName];
            [self setVolatileDomain:newDomain forName:@"ChangedDefaults"];
            [newDomain release];
        }
    }
     - (void)removeObjectForKey:(NSString *)defaultName {
        NSDictionary *changedDomain;
        id oldValue;
         [super removeObjectForKey:defaultName];
        changedDomain = [self volatileDomainForName:@"ChangedDefaults"];
        oldValue = [changedDomain objectForKey:defaultName];
        if (oldValue) { // Something to do
            NSMutableDictionary *newDomain;
            newDomain = [[NSMutableDictionary allocWithZone:[self zone]]
                initWithDictionary:changedDomain];
            [newDomain removeObjectForKey:defaultName];
            [self setVolatileDomain:newDomain forName:@"ChangedDefaults"];
            [newDomain release];
        }
    }

 


Reference

64605

Releases

Rhapsody Developer

Platforms

HP-UX

Disposition

None

Problem

NSBundles cannot dynamically load code

Description

Unlike Apple's implementations of PDO on other platforms, Foundation in PDO for HP-UX cannot dynamically load code. This is due to limitations in the compiler and Objective-C runtime, which will be resolved in a future release.

Workaround

None


Reference

66538

Releases

Rhapsody Developer

Platforms

All

Disposition

None

Problem

NSString's stringWithFormat: doesn't work with %p or some formatting flags.

Description

Unlike what the documentation seems to say, NSString does not understand all ANSI C printf()-style formatting escapes and flags.

Workaround

Use sprintf() to create the character string with the desired format, then create the NSString from that with stringWithCString:.


Reference

66766

Releases

Rhapsody Developer

Platforms

All

Disposition

None

Problem

NSBundle doesn't load _profile and _debug binaries in bundles.

Description

NSBundles do not attempt to load code from debug or profile versions of their binary code, to which the makefiles append the _debug and _profile suffixes, respectively. If the non-debug or non-profile binary doesn't co-exist in the bundle, no code is loaded. NSBundle doesn't care how the binary has been compiled, it just only looks for the file with the name given by the NSExecutable key in the Info.plist file in the bundle's Resources directory.

Workaround

Mach, Solaris, HP-UX: Create a symbolic link named without the _profile or _debug suffix to the _profile or _debug binary at the top level of the bundle directory. All platforms: Copy the _profile or _debug binary to a file of the same name without that suffix. All platforms: Modify the value of the NSExecutable key in the Info.plist file to include the desired _profile or _debug suffix.


Reference

68155

Releases

Rhapsody Developer

Platforms

Windows

Disposition

None

Problem

NSUserDefaults does not reflect Windows Registry case semantics.

Description

The Windows Registry is case-preserving but case-insensitive with respect to registry keys (not default keys). NSUserDefaults doesn't reflect this in its behavior, so, for example, if a persistent domain "MyApp" exists, and a persistent domain "MYAPP" is created, the new domain will eradicate the existing one and all defaults in the existing one will be lost. This does not affect default keys or values, only domain names.

Workaround

None


Reference

68449

Releases

Rhapsody Developer

Platforms

Windows

Disposition

None

Problem

Cannot get a proxy for a distributed OLE object using Distributed Objects.

Description

When trying to get a proxy for an OLE object, you may get the following error: "deserializeObjectAt: class 'NSDistantIDispatchProxy' not loaded".

Workaround

Include nxorb.m (from NextDeveloper/Libraries ) in your client. Although the D'OLE Developer's Guide states that nxorb.m is only needed for use with NXConnections, it's needed in some circumstances for NSConnections as well.


Reference

68675

Releases

Rhapsody Developer

Platforms

HP-UX

Disposition

None

Problem

Multi-threaded Distributed Objects example occasionally hangs on HP-UX.

Description

If you compile the multithreaded Distributed Objects example in /NextDeveloper/Examples/Foundation/MultiThreadedDO and then run it, the program will occasionally hang.

Workaround

None


Reference

69110

Releases

Rhapsody Developer

Platforms

All

Disposition

None

Problem

(unsigned char)45 and (long long)-1 are ordered ascending.

Description

This is actually correct behavior, in that NSNumber follows the C type promotion rules. Thus, the (long long)-1 is promoted to (unsigned long long)18446744073709551615 and (unsigned char)45 is promoted to (unsigned long long)45, and then the comparison makes sense. This is, however, not all that desirable.

Workaround

None


Reference

69152

Releases

Rhapsody Developer

Platforms

HP-UX

Disposition

None

Problem

The HP-UX nmserver has problems passing large structures in the absence of a protocol.

Description

On HP-UX systems, passing large structures over Distributed Objects without having first defined a protocol can cause the nmserver to cease functioning.

Workaround

None


Reference

71118

Releases

Rhapsody Developer

Platforms

All

Disposition

None

Problem

Collections that contain themselves cannot describe themselves.

Description

Invoking the NSObject description method on collection objects that contain themselves, or that contain objects that contain the collection, causes infinite recursion.

Workaround

None


Reference

73320

Releases

Rhapsody Developer

Platforms

All

Disposition

None

Problem

In NSNumberFormatter, specifying different formats for negative and positive values causes problems.

Description

When the formats specified for positive and negative values aren't alike in their treatment of separators, the positive format takes on the separator characteristics of the negative format. Consider, as an example, the following statement:

[numForm setFormat:@"###,##0.00;-(##0.00)"];

Here, positive values will be displayed without thousand separators even though their format includes separators.

Workaround

None


Reference

73686

Releases

Rhapsody Developer

Platforms

All

Disposition

None

Problem

NSFileHandle does not handle error notification correctly.

Description

If an error occurs when application code attempts a background monitoring operation, NSFileHandle may send an empty notification to observers. This sometimes occurs when a native file handle has not been configured correctly for use.

Workaround

None


Reference

77202

Releases

Rhapsody Developer

Platforms

All

Disposition

None

Problem

NSFileManager methods don't work on strict 8.3 DOS file systems.

Description

The NSFileManager methods createFileAtPath:contents:attributes: and movePath:toPath:handler: can fail on FAT file systems which are strict about 8.3 file names, such as the FAT file system on Mach. The FAT file systems of Windows NT and Windows 95 are more forgiving.

Workaround

None


Reference

77309

Releases

Rhapsody Developer

Platforms

All

Disposition

None

Problem

Local proxies are not immediately released when the remote proxy is released.

Description

For performance reasons, Distributed Objects batches, on the remote side, release messages destined for local proxies. Whenever a synchronous message (that is, a non-oneway message) is sent to a remote object, all pending releases on local objects are returned with the return value of the method (which may be void of course). Since the local proxy retains the object it represents (part of its function is to make sure the local object which has been vended remains valid at least as long as there is an outstanding remote proxy for it), a local object which has been vended over the wire, but released on the server side, will persist until the client sends a synchronous message to the server. If a client and server communicate only with oneway messages, local objects which are sent remotely by proxy (as a parameter for example) will persist "forever", or until the local connection is invalidated. This can be a problem for long-lived clients which maintain a persistent connection to a server.

Workaround

Occasionally send a synchronous message from the client to the server. The message does not have to have a return value or parameters, or do anything, but will serve to flush pended releases back to the client. Another workaround would be to occasionally invalidate the connection to the server and reconnect.


Reference

77559

Releases

Rhapsody Developer

Platforms

Mach, HP-UX, Solaris

Disposition

None

Problem

Process name is empty string.

Description

If argv[0] of a process is not an absolute path, and the Foundation can't find argv[0] by searching the PATH environment variable to compute the absolute path, the process-name computation may result in the empty string. This can only happen if a process uses fork() and execve() (or related function) to create a Foundation-based process, and the first argument to execve() specifies an executable which does not exist in the PATH list and the argv[0] passed into execve() is not that same full path, but a relative one. There isn't anything the Foundation can do in this case about computing the full path to the executable, in order to, for example, compute the main bundle path. However, the process name should not be an empty string, but rather the last component of argv[0] unchanged. An empty string for the process name causes trouble for other Foundation subsystems, like user defaults.

Workaround

Pass the same string in argv[0] as the first argument to execve() or related function.


Reference

2380134

Releases

Mac OS X Server

Platforms

All

Disposition

None

Problem

Using NSURL to load files from pre-HTTP/1.0 servers may crash Foundation

Description

If NSURL is used to load a file from an HTTP server, and that HTTP server's responses do not start with a standard status line (as per the HTTP/1.0 specification), then NSURL will raise in the background thread. This will cause the process to crash. This is only likely a problem with HTTP/0.9 and earlier servers.

Workaround

No simple workaround exists. It would be possible to write a new HTTP client implementation in a new subclass of NSURLHandle, then register the subclass with NSURLHandle; this would successfully avoid the Foundation crash, but obviously requires a great deal of work.